しがないOLのはじめてのJava(3)クラスについて
はじめに
こんにちは。クニ吉です。
先日この「クニ吉」の読み方を「くによし」と思っている方がいたのですが、正しくは「くにきち」です。
私の苗字には「くに」が入っていて、会社で「くに太郎」やら「くに吉(きち)」やら呼ばれていたので、それを使いました。最近は「タロさん(太郎が変化)」と呼ばれてて、もう私の要素が全くないのですが・・・;
執筆者名を「くにきち」と平仮名にしようかなと思いつつ、とりあえず現状維持で。(そのうちいきなり変わるかもしれません。)
さて、今回は「クラス」について書きたいと思います。
本ブログの構成
- クラスとは
- クラスの宣言
- クラスに付与できる修飾子
- クラス名の決定
- まとめ
- おわりに
クラスとは
Javaのソースコードは、フィールドやメソッドという処理内容を記述しているものなどで構成されています。
例えば足し算をしたり引き算をしたりといった処理はフィールドやメソッドで記述されますが、そういったフィールドやメソッドをまとめているのが「クラス」です。
フィールドやメソッドなどのクラスの構成要素を「メンバー(または、クラスメンバー)」と呼びます。
ただし、メンバーはなんでもいいわけではありません。
「class」には「同じような人・物の集まり」という意味がありますが、Javaのクラスも「同じ性質」のメンバーを集めます。
例えば、冒頭の足し算や引き算をするメソッドは「計算をおこなう」という同じ性質を有しているため、「Calculation」というクラスを作成できます。
Calculationクラスは何か計算をしてくれるものなんだな、ということが直感的にわかります。
クラスの宣言
このブログの第一回目でも登場したHelloWorldクラスですが、この部分が「クラスの宣言」ですね。
public class HelloWorld { ...(処理) }
クラスの宣言は以下のようなルールで記述します。
構文:[修飾子] class [クラス名] { ...(変数やメソッドなどクラスの中身) }
クラスに付与できる修飾子
修飾子は様々な効果や制限を付与します。
「クラスに付与できる」と書いた通り、修飾子はクラスだけではなく、フィールドやメソッドにも付与できますが、この項ではクラスに付与できるもののみを記述します。(クラスの中に定義するクラス(内部クラス)も今回は除外)
修飾子の説明の中で「?」なものがあると思いますので、後述の「クラス修飾子およびキーワードに関連する補足」を併せてご確認ください。
アクセス修飾子
アクセス範囲を指定する修飾子のことで、指定された修飾子によりクラスのアクセス可能範囲が異なります。
クラス宣言で使えるアクセス修飾子は2種類です。
修飾子 | 説明 |
---|---|
public | 他のどのクラスからでもアクセスを可能とするクラスに付与します |
(修飾子なし) | 同一パッケージ内のクラスからのみアクセスを可能とするクラスとなります。(パッケージプライベート)※補足あり |
それ以外の修飾子
アクセス修飾子に追加して付与することができる修飾子で、クラスの性質を明記します。
※補足あり
修飾子 | 説明 | 使い方 |
---|---|---|
abstract | 継承されるクラス(スーパークラス)に付与します。 | [アクセス修飾子] abstract class [クラス名] { ... } |
final | 継承されたくないクラスに使用します。(付与されたクラスはサブクラスを作れません) | [アクセス修飾子] final class [クラス名] { ... } |
クラス宣言に関係するキーワード
修飾子とは異なる、クラスの性質を明記するキーワードがあります。
※補足あり
キーワード | 説明 | 使い方 |
---|---|---|
extends | 継承するクラス(サブクラス)に付与します。 | [アクセス修飾子] class [クラス名] extends [スーパークラス名] { ... } |
implements | インターフェースの実装クラスに付与します。 | [アクセス修飾子] class [クラス名] implements [インターフェース名] { ... } |
クラス修飾子およびキーワードに関連する補足
修飾子やキーワードについて書きましたが、パッケージやスーパークラスなど「?」なものがあったと思いますので、こちらでざっくりと補足説明。
パッケージとは
クラスは同じ性質のメンバーをまとめたものと書きましたが、パッケージはクラスやインタフェース(※後述)をカテゴリーなどでまとめたもので、階層構造で管理します。
あらためてパッケージプライベートとは
アクセス修飾子の中で出てきた「パッケージプライベート」とは、同じパッケージ内にあるクラスからであればアクセスできる、というもので、上図でいうとclassDがパッケージプライベートの場合、classAやclassBからはアクセスできないことになります。(classFはアクセス可能)
パッケージが異なる場合は全く別物と扱われるので、別パッケージで使用されているクラス名をつけることもできます。
スーパークラスとサブクラスとは
スーパークラスとサブクラスを説明する際に「継承」という仕組みを理解する必要があります。
まず、クラスは子どものクラスを持つことができ、親クラスのことを「スーパークラス」、子クラスのことを「サブクラス」と呼びます。
サブクラスはスーパークラスの持っている値やメソッドを使うことができ、これを「継承」と言います。
親の能力を子どもが継承し、さらに子どもはさらなる能力を持つことができるというイメージです。
共通する機能はスーパークラス(親)が持ち、個別の機能は抽象化して、サブクラスで抽象化した機能の実装を記述する、などといった感じで利用します。
スーパークラスで抽象化したメソッドを「抽象メソッド」と呼び、抽象メソッドを持つクラスは「抽象クラス」と呼びます。
継承のイメージ:
あらためて関連する修飾子とキーワードについて
- abstract → スーパークラスであることを表す
- final → サブクラスを作らない、サブクラス禁止クラスであることを表す
- extends → サブクラスであることを表す
インターフェイスとは
インターフェースとは、抽象メソッドしかもたない「クラスのようなもの」です。
implementsを付与したクラスを「インターフェースの実装クラス」と呼び、実装クラスではインターフェースに記述されているすべての抽象メソッドの実装を記述する必要があります。
例えば以下のような使い方ができます。
- 文字加工インターフェース
- 文字加工に関する何らかの説明を出力する、という抽象メソッド
- 何らかの文字加工処理をする、という抽象メソッド
- 実装クラス1(文字を小文字にする)
- 文字を小文字にするという説明を出力する
- 文字を小文字にする処理
- 実装クラス2(文字を大文字にする)
- 文字を大文字にするという説明を出力する
- 文字を大文字にする処理
・・・など、以下のイメージ図をご参照ください。
実装クラスはインターフェースを通じて呼び出しを行います。
利用する側は、それぞれの実装クラスを指定せずに呼び出しができますので、仮に「小文字を削除する文字加工」という実装クラスが増えたしても、呼び出し側のソースコードを変更する必要がありません。
インターフェースが実装クラスを包んで外側へ処理を隠しているように、詳細なデータやメソッドを外側から隠蔽することを「カプセル化」と言います。
抽象クラスとインターフェースは似ていますが、両者は以下のような感じで使い分ければいいと思います。
- 抽象クラスは「処理の再利用(共通処理など)」をしたい時
- インターフェースは「型定義」をしたい時(実装クラスの仕様書)
あらためて関連する修飾子とキーワードについて
- implements → インターフェースの実装クラスであることを表す
今回はクラスの話なので、この辺で。
クラス名の決定
第一回目のHelloWorldクラスでは、「HelloWorld」がクラス名にあたります。
クラス名は必ず大文字から始め、「名詞」にすることを意識しましょう。
名前、超重要!
「クラスとは」の項で「直感的にわかります」と書きましたが、名前付けは本当に重要です。
このクラスは何をしてくれるのか、このメソッドは何をしてくれるのか、この変数は何を格納してくれるのか・・・。
ひとつのシステムを動かすのにはたくさんのクラスやメソッド、変数を定義する必要がありますが、そのひとつひとつが何をしているのかわからない名前だと、そのクラスやメソッドを使う側はソースコードを全て読まなければなりません。
そのために名前付けや、今回は書きませんが「Javadoc」というソースコードの中に書く説明文を記述することがとても大事です。
コードは書くよりも読む時間の方が圧倒的に多いと言います。
「3日後の自分は他人」と言うほど、自分のソースコードでさえも少し時間が経っただけで読めなくなるくらいなので(過去、Accessで自分の書いたソースコードがわからなくなった経験あり;)、ソースコードの可読性は極めて重要です。
そのひとつとして名前付けについても軽視せず、そのクラスやメソッドを「名前」で表現できることが理想です。(私も師匠に突っ込まれたりしているので、命名道を極めるには先行き長め・・)
ちなみに名前付けを支援するサイトもあるようなので、こういったものを試してみるのも良いかもしれません。
名前付けに関するブログなどでもいろいろあり、参考になります。
まとめ
- クラスとは「同じ性質の処理」をまとめたもの
- 修飾子はクラスのアクセス範囲や特徴を表現するもの
- クラス名は「名詞」にし、大文字から始める
- 名前は重要(ネーミング辞書やさまざまな記事が参考になる)
おわりに
パッケージやらインターフェースやらの説明を書いたら、長くなってしまいました。。
自分の備忘録兼私みたいな非エンジニアでも始められうように・・と思って書き始めたけど、どう書いていくべきか悩んだりします。
結構難しい。